﻿Imports System
Imports System.CodeDom
Imports System.Collections
Imports System.Collections.Generic
Imports System.Diagnostics.CodeAnalysis
Imports System.Globalization
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend Class Parser
        ' Methods
        <SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity"), SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")> _
        Friend Sub New(ByVal validation As RuleValidation)
            Me.validation = validation
            Dim types As Type() = Nothing
            Dim typeProvider As ITypeProvider = validation.GetTypeProvider
            If (typeProvider Is Nothing) Then
                Try 
                    types = validation.ThisType.Assembly.GetTypes
                Catch exception As ReflectionTypeLoadException
                    types = exception.Types
                End Try
            Else
                types = typeProvider.GetTypes
            End If
            Dim dictionary As New Dictionary([Of] String, NamespaceSymbol)
            Dim dictionary2 As New Dictionary([Of] String, Object)
            Dim symbol As NamespaceSymbol = Nothing
            Dim symbol2 As Symbol = Nothing
            Dim symbol3 As NamespaceSymbol = Nothing
            Dim i As Integer
            For i = 0 To types.Length - 1
                Dim type As Type = types(i)
                If (((Not type Is Nothing) AndAlso ((Not type.IsNotPublic OrElse (type.Assembly Is Nothing)) OrElse (type.Assembly Is validation.ThisType.Assembly))) AndAlso Not type.IsNested) Then
                    Dim str As String = type.Namespace
                    If String.IsNullOrEmpty(str) Then
                        If (symbol3 Is Nothing) Then
                            symbol3 = New NamespaceSymbol
                            dictionary.Add("", symbol3)
                        End If
                        symbol = symbol3
                    Else
                        Dim strArray As String() = str.Split(New Char() { "."c })
                        If Not dictionary.TryGetValue(strArray(0), symbol) Then
                            symbol = New NamespaceSymbol(strArray(0), Nothing)
                            dictionary.Add(strArray(0), symbol)
                            Me.globalUniqueSymbols.Item(strArray(0)) = symbol
                        End If
                        If (strArray.Length > 1) Then
                            Dim j As Integer
                            For j = 1 To strArray.Length - 1
                                symbol = symbol.AddNamespace(strArray(j))
                                If Me.globalUniqueSymbols.TryGetValue(strArray(j), symbol2) Then
                                    Dim symbol4 As NamespaceSymbol = [TryCast](symbol2,NamespaceSymbol)
                                    If ((Not symbol4 Is Nothing) AndAlso (Not symbol4.Parent Is symbol.Parent)) Then
                                        If (symbol4.Level = symbol.Level) Then
                                            dictionary2.Item(strArray(j)) = Nothing
                                        ElseIf (symbol.Level < symbol4.Level) Then
                                            Me.globalUniqueSymbols.Item(strArray(j)) = symbol
                                        End If
                                    End If
                                Else
                                    Me.globalUniqueSymbols.Add(strArray(j), symbol)
                                End If
                            Next j
                        End If
                    End If
                    symbol.AddType(type)
                End If
            Next i
            Dim str2 As String
            For Each str2 In dictionary2.Keys
                Me.globalUniqueSymbols.Remove(str2)
            Next
            Dim queue As New Queue([Of] NamespaceSymbol)
            Dim symbol5 As NamespaceSymbol
            For Each symbol5 In dictionary.Values
                queue.Enqueue(symbol5)
            Next
            dictionary2.Clear
            Do While (queue.Count > 0)
                Dim symbol6 As Symbol
                For Each symbol6 In queue.Dequeue.NestedSymbols.Values
                    Dim item As NamespaceSymbol = [TryCast](symbol6,NamespaceSymbol)
                    If (Not item Is Nothing) Then
                        queue.Enqueue(item)
                    Else
                        Dim name As String = symbol6.Name
                        If Me.globalUniqueSymbols.TryGetValue(name, symbol2) Then
                            If Not TypeOf symbol2 Is NamespaceSymbol Then
                                Dim base2 As TypeSymbolBase = DirectCast(symbol2, TypeSymbolBase)
                                Dim typeSymBase As TypeSymbolBase = DirectCast(symbol6, TypeSymbolBase)
                                Dim symbol8 As OverloadedTypeSymbol = base2.OverloadType(typeSymBase)
                                If (symbol8 Is Nothing) Then
                                    dictionary2.Item(name) = Nothing
                                Else
                                    Me.globalUniqueSymbols.Item(name) = symbol8
                                End If
                            End If
                            [Continue] For
                        End If
                        Me.globalUniqueSymbols.Add(name, symbol6)
                    End If
                Next
            Loop
            Dim str4 As String
            For Each str4 In dictionary2.Keys
                Me.globalUniqueSymbols.Remove(str4)
            Next
            Dim thisType As Type = validation.ThisType
            Dim info As MemberInfo
            For Each info In thisType.GetMembers((BindingFlags.FlattenHierarchy Or (BindingFlags.NonPublic Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance)))))
                Dim info2 As PropertyInfo
                Dim type3 As Type
                Dim symbol9 As TypeSymbol
                Dim symbol10 As OverloadedTypeSymbol
                Select Case info.MemberType
                    Case MemberTypes.Property
                        info2 = DirectCast(info, PropertyInfo)
                        Dim indexParameters As ParameterInfo() = info2.GetIndexParameters
                        If ((indexParameters Is Nothing) OrElse (indexParameters.Length <= 0)) Then
                            Exit Select
                        End If
                        Dim info3 As MethodInfo
                        For Each info3 In info2.GetAccessors(True)
                            If ((info3.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(info3, thisType)) Then
                                Me.localUniqueSymbols.Item(info.Name) = New MemberSymbol(info3)
                            End If
                        Next
                        goto Label_06A0
                    Case MemberTypes.TypeInfo, MemberTypes.NestedType
                        type3 = DirectCast(info, Type)
                        symbol9 = New TypeSymbol(type3)
                        If Not Me.globalUniqueSymbols.TryGetValue(symbol9.Name, symbol2) Then
                            goto Label_0676
                        End If
                        Dim base4 As TypeSymbolBase = [TryCast](symbol2,TypeSymbolBase)
                        If (base4 Is Nothing) Then
                            goto Label_0645
                        End If
                        symbol10 = base4.OverloadType(symbol9)
                        If (Not symbol10 Is Nothing) Then
                            goto Label_0619
                        End If
                        If ((info.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(type3, thisType)) Then
                            Me.globalUniqueSymbols.Item(symbol9.Name) = symbol9
                        End If
                        goto Label_06A0
                    Case MemberTypes.Field
                        If ((info.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(DirectCast(info, FieldInfo), thisType)) Then
                            Me.localUniqueSymbols.Item(info.Name) = New MemberSymbol(info)
                        End If
                        goto Label_06A0
                    Case MemberTypes.Method
                        Dim methodInfo As MethodInfo = DirectCast(info, MethodInfo)
                        If ((Not methodInfo.IsSpecialName AndAlso Not methodInfo.IsGenericMethod) AndAlso ((info.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(methodInfo, thisType))) Then
                            Me.localUniqueSymbols.Item(info.Name) = New MemberSymbol(info)
                        End If
                        goto Label_06A0
                    Case Else
                        goto Label_06A0
                End Select
                If (info.DeclaringType Is thisType) Then
                    Me.localUniqueSymbols.Item(info.Name) = New MemberSymbol(info)
                Else
                    Dim info4 As MethodInfo
                    For Each info4 In info2.GetAccessors(True)
                        If ParserContext.IsNonPrivate(info4, thisType) Then
                            Me.localUniqueSymbols.Item(info.Name) = New MemberSymbol(info)
                            Exit For
                        End If
                    Next
                End If
                goto Label_06A0
            Label_0619:
                If ((info.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(type3, thisType)) Then
                    Me.globalUniqueSymbols.Item(symbol9.Name) = symbol10
                End If
                goto Label_06A0
            Label_0645:
                If ((info.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(DirectCast(info, Type), thisType)) Then
                    Me.globalUniqueSymbols.Item(symbol9.Name) = symbol9
                End If
                goto Label_06A0
            Label_0676:
                If ((info.DeclaringType Is thisType) OrElse ParserContext.IsNonPrivate(type3, thisType)) Then
                    Me.globalUniqueSymbols.Item(symbol9.Name) = symbol9
                End If
            Label_06A0:
            Next
        End Sub

        Private Function ConstructCustomType(ByVal type As Type, ByVal arguments As List([Of] CodeExpression), ByVal lparenPosition As Integer) As Object
            Dim str As String
            Dim constructors As ConstructorInfo() = type.GetConstructors((BindingFlags.Public Or BindingFlags.Instance))
            Dim candidateConstructors As List([Of] CandidateConstructor) = Me.GetCandidateConstructors(constructors, arguments)
            If ((candidateConstructors Is Nothing) OrElse (candidateConstructors.Count = 0)) Then
                str = String.Format(CultureInfo.CurrentCulture, Messages.UnknownMethod, New Object() { type.Name, RuleDecompiler.DecompileType(type) })
                Throw New RuleSyntaxException(&H137, str, lparenPosition)
            End If
            Dim constructor As CandidateConstructor = Parser.FindBestConstructor(candidateConstructors)
            If (constructor Is Nothing) Then
                str = String.Format(CultureInfo.CurrentCulture, Messages.AmbiguousConstructor, New Object() { type.Name })
                Throw New RuleSyntaxException(&H54A, str, lparenPosition)
            End If
            Dim obj2 As Object = Nothing
            Try 
                obj2 = constructor.InvokeConstructor
            Catch exception As TargetInvocationException
                If (exception.InnerException Is Nothing) Then
                    Throw
                End If
                Throw New RuleSyntaxException(&H137, exception.InnerException.Message, lparenPosition)
            End Try
            Return obj2
        End Function

        Private Shared Function FindBestConstructor(ByVal candidates As List([Of] CandidateConstructor)) As CandidateConstructor
            Dim count As Integer = candidates.Count
            Dim list As New List([Of] CandidateConstructor)(1) { candidates.Item(0) }
            Dim i As Integer
            For i = 1 To count - 1
                Dim item As CandidateConstructor = candidates.Item(i)
                Dim other As CandidateConstructor = list.Item(0)
                Dim num3 As Integer = item.CompareConstructor(other)
                If (num3 > 0) Then
                    list.Clear
                    list.Add(item)
                ElseIf (num3 = 0) Then
                    list.Add(item)
                End If
            Next i
            If (list.Count = 1) Then
                Return list.Item(0)
            End If
            Return Nothing
        End Function

        Private Function GetCandidateConstructors(ByVal allCtors As ConstructorInfo(), ByVal arguments As List([Of] CodeExpression)) As List([Of] CandidateConstructor)
            If ((allCtors Is Nothing) OrElse (allCtors.Length = 0)) Then
                Return Nothing
            End If
            Dim count As Integer = arguments.Count
            Dim list As New List([Of] CandidateConstructor)(allCtors.Length)
            Dim i As Integer
            For i = 0 To allCtors.Length - 1
                Dim ctor As ConstructorInfo = allCtors(i)
                Dim parameters As ParameterInfo() = ctor.GetParameters
                If (parameters.Length = 0) Then
                    If (count = 0) Then
                        list.Add(New CandidateConstructor(ctor, New Object(0  - 1) {}, False))
                        Return list
                    End If
                    [Continue] For
                End If
                Dim length As Integer = parameters.Length
                Dim index As Integer = length
                Dim info2 As ParameterInfo = parameters((length - 1))
                If info2.ParameterType.IsArray Then
                    Dim customAttributes As Object() = info2.GetCustomAttributes(GetType(ParamArrayAttribute), False)
                    If ((Not customAttributes Is Nothing) AndAlso (customAttributes.Length > 0)) Then
                        index -= 1
                    End If
                End If
                If ((count >= index) AndAlso ((index <> length) OrElse (count = length))) Then
                    Dim ctorArgs As Object() = New Object(length  - 1) {}
                    Dim num5 As Integer = 0
                    Do While (num5 < index)
                        Dim obj2 As Object = Me.MatchArgument(parameters(num5).ParameterType, arguments.Item(num5))
                        If (obj2 Is Nothing) Then
                            Exit Do
                        End If
                        ctorArgs(num5) = obj2
                        num5 += 1
                    Loop
                    If (num5 = index) Then
                        If (index = length) Then
                            list.Add(New CandidateConstructor(ctor, ctorArgs, False))
                            [Continue] For
                        End If
                        If (count = index) Then
                            list.Add(New CandidateConstructor(ctor, ctorArgs, True))
                            [Continue] For
                        End If
                        If ((count = (index + 1)) AndAlso (Me.validation.ExpressionInfo(arguments.Item(num5)).ExpressionType Is GetType(NullLiteral))) Then
                            list.Add(New CandidateConstructor(ctor, ctorArgs, False))
                            [Continue] For
                        End If
                        Dim parameterType As Type = parameters(num5).ParameterType
                        Dim elementType As Type = parameterType.GetElementType
                        Dim array As Array = DirectCast(parameterType.InvokeMember(parameterType.Name, BindingFlags.CreateInstance, Nothing, Nothing, New Object() { (count - index) }, CultureInfo.CurrentCulture), Array)
                        ctorArgs(index) = array
                        Do While (num5 < count)
                            Dim obj3 As Object = Me.MatchArgument(elementType, arguments.Item(num5))
                            If (obj3 Is Nothing) Then
                                Exit Do
                            End If
                            array.SetValue(obj3, CInt((num5 - index)))
                            num5 += 1
                        Loop
                        If (num5 = count) Then
                            list.Add(New CandidateConstructor(ctor, ctorArgs, (index <> length)))
                        End If
                    End If
                End If
            Next i
            Return list
        End Function

        Friend Function GetExpressionCompletions(ByVal expressionString As String) As ICollection
            Try 
                Dim parserContext As ParserContext = New IntellisenseParser(expressionString).BackParse
                If (Not parserContext Is Nothing) Then
                    Dim currentToken As Token = parserContext.CurrentToken
                    If ((parserContext.NumTokens = 2) AndAlso (currentToken.TokenID = TokenID.Identifier)) Then
                        Dim str As String = CStr(currentToken.Value)
                        If (str.Length = 1) Then
                            Return Me.GetRootCompletions(str.Chars(0))
                        End If
                    Else
                        Me.validation.Errors.Clear
                        Me.ParsePostfixExpression(parserContext, True, ValueCheck.Read)
                        Return parserContext.completions
                    End If
                End If
            Catch exception As RuleSyntaxException
                If (exception.ErrorNumber <> 0) Then
                    Return Nothing
                End If
            End Try
            Return Nothing
        End Function

        Private Function GetRootCompletions(ByVal firstCharacter As Char) As ICollection
            Dim list As New ArrayList
            Dim upperFirstCharacter As Char = Char.ToUpper(firstCharacter, CultureInfo.InvariantCulture)
            Dim pair As KeyValuePair([Of] String, Symbol)
            For Each pair In Me.globalUniqueSymbols
                Dim key As String = pair.Key
                If (Char.ToUpper(key.Chars(0), CultureInfo.InvariantCulture) = upperFirstCharacter) Then
                    Dim symbol As Symbol = Nothing
                    If Not Me.localUniqueSymbols.TryGetValue(key, symbol) Then
                        pair.Value.RecordSymbol(list)
                    End If
                End If
            Next
            Dim pair2 As KeyValuePair([Of] String, Symbol)
            For Each pair2 In Me.localUniqueSymbols
                If (Char.ToUpper(pair2.Key.Chars(0), CultureInfo.InvariantCulture) = upperFirstCharacter) Then
                    pair2.Value.RecordSymbol(list)
                End If
            Next
            Scanner.AddKeywordsStartingWith(upperFirstCharacter, list)
            Return list
        End Function

        Private Function MatchArgument(ByVal parameterType As Type, ByVal arg As CodeExpression) As Object
            Dim fromType As Type = arg.GetType
            If TypeProvider.IsAssignable(parameterType, fromType) Then
                Return arg
            End If
            Dim rhsExpression As CodePrimitiveExpression = [TryCast](arg,CodePrimitiveExpression)
            If (Not rhsExpression Is Nothing) Then
                Dim error As ValidationError = Nothing
                If RuleValidation.TypesAreAssignable(Me.validation.ExpressionInfo(rhsExpression).ExpressionType, parameterType, rhsExpression, [error]) Then
                    Return rhsExpression.Value
                End If
            End If
            Return Nothing
        End Function

        Private Function ParseArgument(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim expression As CodeExpression = Nothing
            Dim currentToken As Token = parserContext.CurrentToken
            Dim startPosition As Integer = currentToken.StartPosition
            Dim nullable As Nullable([Of] FieldDirection) = Nothing
            Dim read As ValueCheck = ValueCheck.Read
            Select Case currentToken.TokenID
                Case TokenID.In
                    nullable = New Nullable([Of] FieldDirection)(FieldDirection.In)
                    parserContext.NextToken
                    Exit Select
                Case TokenID.Out
                    nullable = New Nullable([Of] FieldDirection)(FieldDirection.Out)
                    parserContext.NextToken
                    read = ValueCheck.Write
                    Exit Select
                Case TokenID.Ref
                    nullable = New Nullable([Of] FieldDirection)(FieldDirection.Ref)
                    parserContext.NextToken
                    read = (ValueCheck.Write Or ValueCheck.Read)
                    Exit Select
            End Select
            expression = Me.ParseBinaryExpression(parserContext, 0, True, read)
            If nullable.HasValue Then
                expression = New CodeDirectionExpression(nullable.Value, expression)
                parserContext.exprPositions.Item(expression) = startPosition
                Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            End If
            Return expression
        End Function

        Private Function ParseArgumentList(ByVal parserContext As ParserContext) As List([Of] CodeExpression)
            Dim list As New List([Of] CodeExpression)
            If (parserContext.CurrentToken.TokenID <> TokenID.RParen) Then
                Dim item As CodeExpression = Me.ParseArgument(parserContext, True)
                list.Add(item)
                Do While (parserContext.CurrentToken.TokenID = TokenID.Comma)
                    parserContext.NextToken
                    item = Me.ParseArgument(parserContext, True)
                    list.Add(item)
                Loop
                If (parserContext.CurrentToken.TokenID <> TokenID.RParen) Then
                    Throw New RuleSyntaxException(&H182, Messages.Parser_MissingRParenAfterArgumentList, parserContext.CurrentToken.StartPosition)
                End If
            End If
            parserContext.NextToken
            Return list
        End Function

        Private Function ParseArrayCreationArguments(ByVal parserContext As ParserContext) As List([Of] CodeExpression)
            If (parserContext.CurrentToken.TokenID <> TokenID.LCurlyBrace) Then
                Return Nothing
            End If
            Dim list As New List([Of] CodeExpression)
            parserContext.NextToken
            If (parserContext.CurrentToken.TokenID <> TokenID.RCurlyBrace) Then
                list.Add(Me.ParseInitializer(parserContext, True))
                Do While (parserContext.CurrentToken.TokenID = TokenID.Comma)
                    parserContext.NextToken
                    list.Add(Me.ParseInitializer(parserContext, True))
                Loop
                If (parserContext.CurrentToken.TokenID <> TokenID.RCurlyBrace) Then
                    Throw New RuleSyntaxException(&H1AB, Messages.Parser_MissingRCurlyAfterInitializers, parserContext.CurrentToken.StartPosition)
                End If
            End If
            parserContext.NextToken
            Return list
        End Function

        Private Shared Function ParseArrayType(ByVal parserContext As ParserContext, ByVal baseType As Type) As Type
            Dim type As Type = baseType
            Do While (parserContext.CurrentToken.TokenID = TokenID.LBracket)
                Dim rank As Integer = 1
                Do While (parserContext.NextToken.TokenID = TokenID.Comma)
                    rank += 1
                Loop
                If (parserContext.CurrentToken.TokenID <> TokenID.RBracket) Then
                    Throw New RuleSyntaxException(410, Messages.Parser_MissingCloseSquareBracket, parserContext.CurrentToken.StartPosition)
                End If
                parserContext.NextToken
                If (rank = 1) Then
                    type = type.MakeArrayType
                Else
                    type = type.MakeArrayType(rank)
                End If
            Loop
            Return type
        End Function

        Private Function ParseAssignmentStatement(ByVal parserContext As ParserContext) As CodeStatement
            Dim statement As CodeStatement = Nothing
            Dim left As CodeExpression = Me.ParsePostfixExpression(parserContext, False, ValueCheck.Read)
            Dim currentToken As Token = parserContext.CurrentToken
            If (currentToken.TokenID = TokenID.Assign) Then
                Dim startPosition As Integer = currentToken.StartPosition
                parserContext.NextToken
                Dim right As CodeExpression = Me.ParseBinaryExpression(parserContext, 0, True, ValueCheck.Read)
                statement = New CodeAssignStatement(left, right)
                parserContext.exprPositions.Item(statement) = startPosition
            Else
                statement = New CodeExpressionStatement(left)
                parserContext.exprPositions.Item(statement) = parserContext.exprPositions.Item(left)
            End If
            Me.ValidateStatement(parserContext, statement)
            Return statement
        End Function

        Private Function ParseBinaryExpression(ByVal parserContext As ParserContext, ByVal precedence As Integer, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck) As CodeExpression
            Dim left As CodeExpression = If((precedence = (Parser.precedences.Length - 1)), Me.ParseUnaryExpression(parserContext, assignIsEquality, check), Me.ParseBinaryExpression(parserContext, (precedence + 1), assignIsEquality, check))
            If (Not left Is Nothing) Then
                Do While True
                    Dim currentToken As Token = parserContext.CurrentToken
                    Dim descriptor2 As BinaryOperationDescriptor = Parser.precedences(precedence).FindOperation(currentToken.TokenID)
                    If (descriptor2 Is Nothing) Then
                        Return left
                    End If
                    parserContext.NextToken
                    Dim right As CodeExpression = If((precedence = (Parser.precedences.Length - 1)), Me.ParseUnaryExpression(parserContext, True, check), Me.ParseBinaryExpression(parserContext, (precedence + 1), True, check))
                    left = descriptor2.CreateBinaryExpression(left, right, currentToken.StartPosition, Me, parserContext, assignIsEquality)
                Loop
            End If
            Return left
        End Function

        Friend Function ParseCondition(ByVal expressionString As String) As RuleExpressionCondition
            Me.validation.Errors.Clear
            Dim parserContext As New ParserContext(expressionString)
            If (parserContext.CurrentToken.TokenID = TokenID.EndOfInput) Then
                Throw New RuleSyntaxException(400, Messages.Parser_EmptyExpression, parserContext.CurrentToken.StartPosition)
            End If
            Dim expression As CodeExpression = Me.ParseBinaryExpression(parserContext, 0, True, ValueCheck.Read)
            If (parserContext.CurrentToken.TokenID <> TokenID.EndOfInput) Then
                Throw New RuleSyntaxException(&H191, Messages.Parser_ExtraCharactersIgnored, parserContext.CurrentToken.StartPosition)
            End If
            If (expression Is Nothing) Then
                Return Nothing
            End If
            Dim info As RuleExpressionInfo = Me.validation.ExpressionInfo(expression)
            If (info Is Nothing) Then
                Return Nothing
            End If
            If Not RuleValidation.IsValidBooleanResult(info.ExpressionType) Then
                Throw New RuleSyntaxException(&H547, Messages.ConditionMustBeBoolean, 0)
            End If
            Return New RuleExpressionCondition(expression)
        End Function

        Private Function ParseConstructorArguments(ByVal parserContext As ParserContext, ByVal type As Type, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
            parserContext.NextToken
            If ((parserContext.CurrentToken.TokenID = TokenID.EndOfInput) AndAlso parserContext.provideIntellisense) Then
                parserContext.SetConstructorCompletions(type, Me.Validator.ThisType)
                Return Nothing
            End If
            Dim argumentExprs As List([Of] CodeExpression) = Me.ParseArgumentList(parserContext)
            If (Not type.IsValueType OrElse (argumentExprs.Count <> 0)) Then
                If type.IsAbstract Then
                    Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.UnknownConstructor, New Object() { RuleDecompiler.DecompileType(type) })
                    Throw New RuleSyntaxException(&H137, message, startPosition)
                End If
                Dim constructorBindingFlags As BindingFlags = (BindingFlags.FlattenHierarchy Or (BindingFlags.Public Or BindingFlags.Instance))
                If (type.Assembly Is Me.validation.ThisType.Assembly) Then
                    constructorBindingFlags = (constructorBindingFlags Or BindingFlags.NonPublic)
                End If
                Dim error As ValidationError = Nothing
                If (Me.validation.ResolveConstructor(type, constructorBindingFlags, argumentExprs, [error]) Is Nothing) Then
                    Throw New RuleSyntaxException([error].ErrorNumber, [error].ErrorText, startPosition)
                End If
            End If
            Dim expression As CodeExpression = New CodeObjectCreateExpression(type, argumentExprs.ToArray)
            parserContext.exprPositions.Item(expression) = startPosition
            Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            Return expression
        End Function

        Private Function ParseElementOperator(ByVal parserContext As ParserContext, ByVal primaryExpr As CodeExpression, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
            parserContext.NextToken
            Dim indices As CodeExpression() = Me.ParseIndexList(parserContext).ToArray
            Dim expression As CodeExpression = Nothing
            If Me.validation.ExpressionInfo(primaryExpr).ExpressionType.IsArray Then
                expression = New CodeArrayIndexerExpression(primaryExpr, indices)
            Else
                expression = New CodeIndexerExpression(primaryExpr, indices)
            End If
            parserContext.exprPositions.Item(expression) = startPosition
            Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            Return expression
        End Function

        Private Function ParseFieldOrProperty(ByVal parserContext As ParserContext, ByVal postfixExpr As CodeExpression, ByVal name As String, ByVal namePosition As Integer, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck) As CodeExpression
            Dim expression As CodeExpression = Nothing
            Dim expressionType As Type = Me.Validator.ExpressionInfo(postfixExpr).ExpressionType
            Dim info As MemberInfo = Me.Validator.ResolveFieldOrProperty(expressionType, name)
            If (info Is Nothing) Then
                Dim type As Type = Me.Validator.ExpressionInfo(postfixExpr).ExpressionType
                Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.UnknownFieldOrProperty, New Object() { name, RuleDecompiler.DecompileType(type) })
                Throw New RuleSyntaxException(390, message, namePosition)
            End If
            If (info.MemberType = MemberTypes.Field) Then
                expression = New CodeFieldReferenceExpression(postfixExpr, name)
            Else
                expression = New CodePropertyReferenceExpression(postfixExpr, name)
            End If
            parserContext.exprPositions.Item(expression) = namePosition
            Me.ValidateExpression(parserContext, expression, assignIsEquality, check)
            Return expression
        End Function

        Private Function ParseGenericType(ByVal parserContext As ParserContext, ByVal candidateGenericTypes As List([Of] Type), ByVal typeName As String) As Type
            Dim typeArguments As Type() = Me.ParseGenericTypeArgList(parserContext)
            Dim type As Type
            For Each type In candidateGenericTypes
                If (type.GetGenericArguments.Length = typeArguments.Length) Then
                    Return type.MakeGenericType(typeArguments)
                End If
            Next
            Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.Parser_BadTypeArgCount, New Object() { typeName })
            Throw New RuleSyntaxException(&H18D, message, parserContext.CurrentToken.StartPosition)
        End Function

        Private Function ParseGenericTypeArgList(ByVal parserContext As ParserContext) As Type()
            Dim list As New List([Of] Type)
            Do
                Dim token As Token = parserContext.NextToken
                Dim item As Type = Me.TryParseTypeSpecifier(parserContext, True)
                If (item Is Nothing) Then
                    Throw New RuleSyntaxException(&H18E, Messages.Parser_InvalidTypeArgument, token.StartPosition)
                End If
                list.Add(item)
            Loop While (parserContext.CurrentToken.TokenID = TokenID.Comma)
            If (parserContext.CurrentToken.TokenID <> TokenID.Greater) Then
                Throw New RuleSyntaxException(&H18F, Messages.Parser_MissingCloseAngleBracket, parserContext.CurrentToken.StartPosition)
            End If
            parserContext.NextToken
            Return list.ToArray
        End Function

        Private Function ParseIndexList(ByVal parserContext As ParserContext) As List([Of] CodeExpression)
            Dim list As New List([Of] CodeExpression)
            Dim item As CodeExpression = Me.ParseBinaryExpression(parserContext, 0, True, ValueCheck.Read)
            list.Add(item)
            Do While (parserContext.CurrentToken.TokenID = TokenID.Comma)
                parserContext.NextToken
                item = Me.ParseBinaryExpression(parserContext, 0, True, ValueCheck.Read)
                list.Add(item)
            Loop
            If (parserContext.CurrentToken.TokenID <> TokenID.RBracket) Then
                Throw New RuleSyntaxException(410, Messages.Parser_MissingCloseSquareBracket, parserContext.CurrentToken.StartPosition)
            End If
            parserContext.NextToken
            Return list
        End Function

        Private Function ParseInitializer(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeExpression
            Return Me.ParseBinaryExpression(parserContext, 0, assignIsEquality, ValueCheck.Read)
        End Function

        Private Function ParseMemberOperator(ByVal parserContext As ParserContext, ByVal primaryExpr As CodeExpression, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck) As CodeExpression
            Dim token As Token = parserContext.NextToken
            If (token.TokenID <> TokenID.Identifier) Then
                If (Not parserContext.provideIntellisense OrElse (token.TokenID <> TokenID.EndOfInput)) Then
                    Throw New RuleSyntaxException(&H185, Messages.Parser_MissingIdentifierAfterDot, parserContext.CurrentToken.StartPosition)
                End If
                parserContext.SetTypeMemberCompletions(Me.validation.ExpressionInfo(primaryExpr).ExpressionType, Me.validation.ThisType, TypeOf primaryExpr Is CodeTypeReferenceExpression, Me.validation)
                Return Nothing
            End If
            Dim methodName As String = CStr(token.Value)
            Dim startPosition As Integer = token.StartPosition
            If (parserContext.NextToken.TokenID = TokenID.LParen) Then
                Return Me.ParseMethodInvoke(parserContext, primaryExpr, methodName, True)
            End If
            Return Me.ParseFieldOrProperty(parserContext, primaryExpr, methodName, startPosition, assignIsEquality, check)
        End Function

        Private Function ParseMethodInvoke(ByVal parserContext As ParserContext, ByVal postfixExpr As CodeExpression, ByVal methodName As String, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
            parserContext.NextToken
            If ((parserContext.CurrentToken.TokenID = TokenID.EndOfInput) AndAlso parserContext.provideIntellisense) Then
                Dim includeStatic As Boolean = TypeOf postfixExpr Is CodeTypeReferenceExpression
                parserContext.SetMethodCompletions(Me.validation.ExpressionInfo(postfixExpr).ExpressionType, Me.validation.ThisType, methodName, includeStatic, Not includeStatic, Me.validation)
                Return Nothing
            End If
            Dim list As List([Of] CodeExpression) = Me.ParseArgumentList(parserContext)
            postfixExpr = New CodeMethodInvokeExpression(postfixExpr, methodName, list.ToArray)
            parserContext.exprPositions.Item(postfixExpr) = startPosition
            Me.ValidateExpression(parserContext, postfixExpr, assignIsEquality, ValueCheck.Read)
            Return postfixExpr
        End Function

        Private Function ParseNestedType(ByVal parserContext As ParserContext, ByVal currentType As Type) As Type
            Dim type As Type = Nothing
            Do While (parserContext.CurrentToken.TokenID = TokenID.Dot)
                Dim tokenValue As Integer = parserContext.SaveCurrentToken
                Dim token As Token = parserContext.NextToken
                If (token.TokenID <> TokenID.Identifier) Then
                    If (Not parserContext.provideIntellisense OrElse (token.TokenID <> TokenID.EndOfInput)) Then
                        Throw New RuleSyntaxException(&H185, Messages.Parser_MissingIdentifierAfterDot, parserContext.CurrentToken.StartPosition)
                    End If
                    parserContext.SetTypeMemberCompletions(currentType, Me.validation.ThisType, True, Me.validation)
                    Return Nothing
                End If
                Dim typeName As String = CStr(token.Value)
                Dim public As BindingFlags = BindingFlags.Public
                If (currentType.Assembly Is Me.validation.ThisType.Assembly) Then
                    [public] = ([public] Or BindingFlags.NonPublic)
                End If
                If (parserContext.NextToken.TokenID = TokenID.Less) Then
                    Dim candidateGenericTypes As New List([Of] Type)
                    Dim nestedTypes As Type() = currentType.GetNestedTypes([public])
                    Dim str2 As String = (typeName & "`")
                    Dim i As Integer
                    For i = 0 To nestedTypes.Length - 1
                        Dim item As Type = nestedTypes(i)
                        If item.Name.StartsWith(str2, StringComparison.Ordinal) Then
                            candidateGenericTypes.Add(item)
                        End If
                    Next i
                    If (candidateGenericTypes.Count = 0) Then
                        parserContext.RestoreCurrentToken(tokenValue)
                        Return currentType
                    End If
                    type = Me.ParseGenericType(parserContext, candidateGenericTypes, typeName)
                    currentType = type
                Else
                    Dim member As MemberInfo() = currentType.GetMember(typeName, [public])
                    If (((member Is Nothing) OrElse (member.Length <> 1)) OrElse ((member(0).MemberType <> MemberTypes.NestedType) AndAlso (member(0).MemberType <> MemberTypes.TypeInfo))) Then
                        parserContext.RestoreCurrentToken(tokenValue)
                        Return currentType
                    End If
                    type = DirectCast(member(0), Type)
                    If (currentType.IsGenericType AndAlso type.IsGenericTypeDefinition) Then
                        type = type.MakeGenericType(currentType.GetGenericArguments)
                    End If
                    currentType = type
                End If
            Loop
            Return type
        End Function

        Private Function ParseObjectCreation(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim expression As CodeExpression = Nothing
            Dim expression2 As CodeExpression
            Dim currentToken As Token = parserContext.CurrentToken
            Dim computedType As Type = Me.TryParseTypeSpecifierWithOptionalSize(parserContext, assignIsEquality, expression2)
            If (parserContext.provideIntellisense AndAlso (parserContext.CurrentToken.TokenID = TokenID.EndOfInput)) Then
                If (Not computedType Is Nothing) Then
                    parserContext.SetNestedClassCompletions(computedType, Me.validation.ThisType)
                End If
                Return Nothing
            End If
            If (computedType Is Nothing) Then
                Throw New RuleSyntaxException(&H18E, Messages.Parser_InvalidTypeArgument, currentToken.StartPosition)
            End If
            If (expression2 Is Nothing) Then
                If (parserContext.CurrentToken.TokenID <> TokenID.LParen) Then
                    Throw New RuleSyntaxException(&H18E, Messages.Parser_InvalidNew, currentToken.StartPosition)
                End If
                Return Me.ParseConstructorArguments(parserContext, computedType, assignIsEquality)
            End If
            Dim list As List([Of] CodeExpression) = Me.ParseArrayCreationArguments(parserContext)
            If (Not list Is Nothing) Then
                If (expression2 Is Parser.defaultSize) Then
                    expression = New CodeArrayCreateExpression(computedType, list.ToArray)
                Else
                    expression = New CodeArrayCreateExpression(computedType, expression2)
                    DirectCast(expression, CodeArrayCreateExpression).Initializers.AddRange(list.ToArray)
                End If
            Else
                If (expression2 Is Parser.defaultSize) Then
                    Throw New RuleSyntaxException(&H1AA, Messages.Parser_NoArrayCreationSize, parserContext.CurrentToken.StartPosition)
                End If
                expression = New CodeArrayCreateExpression(computedType, expression2)
            End If
            Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            Return expression
        End Function

        Private Function ParsePostfixExpression(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck) As CodeExpression
            Dim primaryExpr As CodeExpression = Me.ParsePrimaryExpression(parserContext, assignIsEquality)
            Dim expression2 As CodeExpression = Me.TryParsePostfixOperator(parserContext, primaryExpr, assignIsEquality, check)
            Do While (Not expression2 Is Nothing)
                primaryExpr = expression2
                expression2 = Me.TryParsePostfixOperator(parserContext, primaryExpr, assignIsEquality, check)
            Loop
            Return primaryExpr
        End Function

        Private Function ParsePrimaryExpression(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim expression As CodeExpression = Nothing
            Dim currentToken As Token = parserContext.CurrentToken
            Select Case currentToken.TokenID
                Case TokenID.Identifier
                    Return Me.ParseRootIdentifier(parserContext, assignIsEquality)
                Case TokenID.LParen
                    parserContext.NextToken
                    expression = Me.ParseBinaryExpression(parserContext, 0, assignIsEquality, ValueCheck.Read)
                    parserContext.exprPositions.Item(expression) = currentToken.StartPosition
                    If (parserContext.CurrentToken.TokenID <> TokenID.RParen) Then
                        Throw New RuleSyntaxException(&H184, Messages.Parser_MissingRParenInSubexpression, parserContext.CurrentToken.StartPosition)
                    End If
                    parserContext.NextToken
                    Return expression
                Case TokenID.StringLiteral, TokenID.CharacterLiteral, TokenID.IntegerLiteral, TokenID.DecimalLiteral, TokenID.FloatLiteral, TokenID.True, TokenID.False, TokenID.Null
                    parserContext.NextToken
                    expression = New CodePrimitiveExpression(currentToken.Value)
                    parserContext.exprPositions.Item(expression) = currentToken.StartPosition
                    Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
                    Return expression
                Case TokenID.This
                    parserContext.NextToken
                    expression = New CodeThisReferenceExpression
                    parserContext.exprPositions.Item(expression) = currentToken.StartPosition
                    Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
                    Return expression
                Case TokenID.TypeName
                    parserContext.NextToken
                    Dim type As Type = DirectCast(currentToken.Value, Type)
                    Dim typeRef As New CodeTypeReference(type)
                    Me.validation.AddTypeReference(typeRef, type)
                    expression = New CodeTypeReferenceExpression(typeRef)
                    parserContext.exprPositions.Item(expression) = currentToken.StartPosition
                    Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
                    Return expression
                Case TokenID.New
                    parserContext.NextToken
                    Return Me.ParseObjectCreation(parserContext, assignIsEquality)
                Case TokenID.EndOfInput
                    Throw New RuleSyntaxException(&H183, Messages.Parser_MissingOperand, currentToken.StartPosition)
            End Select
            Throw New RuleSyntaxException(&H187, Messages.Parser_UnknownLiteral, currentToken.StartPosition)
        End Function

        Private Function ParseRootIdentifier(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim currentToken As Token = parserContext.CurrentToken
            Dim key As String = CStr(currentToken.Value)
            Dim symbol As Symbol = Nothing
            If Not Me.localUniqueSymbols.TryGetValue(key, symbol) Then
                Me.globalUniqueSymbols.TryGetValue(key, symbol)
            End If
            If (symbol Is Nothing) Then
                Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.Parser_UnknownIdentifier, New Object() { key })
                Throw New RuleSyntaxException(&H188, message, currentToken.StartPosition)
            End If
            Return symbol.ParseRootIdentifier(Me, parserContext, assignIsEquality)
        End Function

        Friend Function ParseRootNamespaceIdentifier(ByVal parserContext As ParserContext, ByVal nsSym As NamespaceSymbol, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim symbol As Symbol = Nothing
            Do While (Not nsSym Is Nothing)
                Dim token As Token = parserContext.NextToken
                If (token.TokenID <> TokenID.Dot) Then
                    Throw New RuleSyntaxException(&H189, Messages.Parser_MissingDotAfterNamespace, token.StartPosition)
                End If
                token = parserContext.NextToken
                If (token.TokenID <> TokenID.Identifier) Then
                    If (Not parserContext.provideIntellisense OrElse (token.TokenID <> TokenID.EndOfInput)) Then
                        Throw New RuleSyntaxException(&H185, Messages.Parser_MissingIdentifierAfterDot, token.StartPosition)
                    End If
                    parserContext.SetNamespaceCompletions(nsSym)
                    Return Nothing
                End If
                Dim memberName As String = CStr(token.Value)
                symbol = nsSym.FindMember(memberName)
                If (symbol Is Nothing) Then
                    Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.Parser_UnknownNamespaceMember, New Object() { memberName, nsSym.GetQualifiedName })
                    Throw New RuleSyntaxException(&H18A, message, token.StartPosition)
                End If
                nsSym = [TryCast](symbol,NamespaceSymbol)
            Loop
            Return symbol.ParseRootIdentifier(Me, parserContext, assignIsEquality)
        End Function

        Friend Function ParseRootOverloadedTypeIdentifier(ByVal parserContext As ParserContext, ByVal candidateTypeSymbols As List([Of] TypeSymbol), ByVal assignIsEquality As Boolean) As CodeExpression
            Dim currentToken As Token = parserContext.CurrentToken
            Dim typeName As String = CStr(currentToken.Value)
            Dim startPosition As Integer = currentToken.StartPosition
            currentToken = parserContext.NextToken
            Dim currentType As Type = Nothing
            If (currentToken.TokenID = TokenID.Less) Then
                Dim candidateGenericTypes As New List([Of] Type)(candidateTypeSymbols.Count)
                Dim symbol As TypeSymbol
                For Each symbol In candidateTypeSymbols
                    If (symbol.GenericArgCount > 0) Then
                        candidateGenericTypes.Add(symbol.Type)
                    End If
                Next
                currentType = Me.ParseGenericType(parserContext, candidateGenericTypes, typeName)
            Else
                Dim symbol2 As TypeSymbol = candidateTypeSymbols.Find(Function (ByVal s As TypeSymbol) 
                    Return (s.GenericArgCount = 0)
                End Function)
                If (symbol2 Is Nothing) Then
                    Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingTypeArguments, New Object() { typeName })
                    Throw New RuleSyntaxException(&H18B, message, startPosition)
                End If
                currentType = symbol2.Type
            End If
            If (parserContext.CurrentToken.TokenID = TokenID.Dot) Then
                Dim type2 As Type = Me.ParseNestedType(parserContext, currentType)
                If (Not type2 Is Nothing) Then
                    currentType = type2
                End If
            End If
            Return Me.ParseTypeRef(parserContext, currentType, startPosition, assignIsEquality)
        End Function

        Friend Function ParseRootTypeIdentifier(ByVal parserContext As ParserContext, ByVal typeSym As TypeSymbol, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim message As String = Nothing
            Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
            Dim token As Token = parserContext.NextToken
            If ((typeSym.GenericArgCount > 0) AndAlso (token.TokenID <> TokenID.Less)) Then
                message = String.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingTypeArguments, New Object() { typeSym.Name })
                Throw New RuleSyntaxException(&H18B, message, token.StartPosition)
            End If
            Dim type As Type = typeSym.Type
            If (token.TokenID = TokenID.Less) Then
                If (typeSym.GenericArgCount = 0) Then
                    message = String.Format(CultureInfo.CurrentCulture, Messages.Parser_NotAGenericType, New Object() { RuleDecompiler.DecompileType(type) })
                    Throw New RuleSyntaxException(&H18C, message, token.StartPosition)
                End If
                Dim typeArguments As Type() = Me.ParseGenericTypeArgList(parserContext)
                If (typeArguments.Length <> typeSym.GenericArgCount) Then
                    message = String.Format(CultureInfo.CurrentCulture, Messages.Parser_BadTypeArgCount, New Object() { RuleDecompiler.DecompileType(type) })
                    Throw New RuleSyntaxException(&H18D, message, parserContext.CurrentToken.StartPosition)
                End If
                type = Me.Validator.ResolveType(type.AssemblyQualifiedName).MakeGenericType(typeArguments)
            End If
            If (parserContext.CurrentToken.TokenID = TokenID.Dot) Then
                Dim type2 As Type = Me.ParseNestedType(parserContext, type)
                If (Not type2 Is Nothing) Then
                    type = type2
                End If
            End If
            Return Me.ParseTypeRef(parserContext, type, startPosition, assignIsEquality)
        End Function

        <SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
        Friend Function ParseSingleStatement(ByVal statementString As String) As RuleAction
            Me.validation.Errors.Clear
            Dim parserContext As New ParserContext(statementString)
            Dim action As RuleAction = Me.ParseStatement(parserContext)
            If (parserContext.CurrentToken.TokenID <> TokenID.EndOfInput) Then
                Throw New RuleSyntaxException(&H191, Messages.Parser_ExtraCharactersIgnored, parserContext.CurrentToken.StartPosition)
            End If
            Return action
        End Function

        Private Function ParseStatement(ByVal parserContext As ParserContext) As RuleAction
            Dim action As RuleAction = Nothing
            Dim currentToken As Token = parserContext.CurrentToken
            If (currentToken.TokenID = TokenID.Halt) Then
                parserContext.NextToken
                action = New RuleHaltAction
                parserContext.exprPositions.Item(action) = currentToken.StartPosition
                Me.ValidateAction(parserContext, action)
                Return action
            End If
            If (currentToken.TokenID = TokenID.Update) Then
                parserContext.NextToken
                If (parserContext.CurrentToken.TokenID <> TokenID.LParen) Then
                    Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.Parser_MissingLparenAfterCommand, New Object() { "UPDATE" })
                    Throw New RuleSyntaxException(&H180, message, parserContext.CurrentToken.StartPosition)
                End If
                parserContext.NextToken
                Dim path As String = Nothing
                Dim token2 As Token = parserContext.CurrentToken
                If (token2.TokenID = TokenID.StringLiteral) Then
                    path = CStr(token2.Value)
                    parserContext.NextToken
                Else
                    Dim expression As CodeExpression = Me.ParsePostfixExpression(parserContext, True, ValueCheck.Read)
                    Dim analysis As New RuleAnalysis(Me.validation, True)
                    RuleExpressionWalker.AnalyzeUsage(analysis, expression, False, True, Nothing)
                    Dim symbols As ICollection([Of] String) = analysis.GetSymbols
                    If ((symbols.Count = 0) OrElse (symbols.Count > 1)) Then
                        Throw New RuleSyntaxException(&H181, Messages.Parser_InvalidUpdateExpression, token2.StartPosition)
                    End If
                    Dim enumerator As IEnumerator([Of] String) = symbols.GetEnumerator
                    enumerator.MoveNext
                    path = enumerator.Current
                End If
                If (parserContext.CurrentToken.TokenID <> TokenID.RParen) Then
                    Throw New RuleSyntaxException(&H182, Messages.Parser_MissingRParenAfterArgumentList, parserContext.CurrentToken.StartPosition)
                End If
                parserContext.NextToken
                action = New RuleUpdateAction(path)
                parserContext.exprPositions.Item(action) = currentToken.StartPosition
                Me.ValidateAction(parserContext, action)
                Return action
            End If
            Dim tokenValue As Integer = parserContext.SaveCurrentToken
            Dim fromType As Type = Me.TryParseTypeSpecifier(parserContext, False)
            If (((Not fromType Is Nothing) AndAlso (parserContext.CurrentToken.TokenID = TokenID.LParen)) AndAlso TypeProvider.IsAssignable(GetType(RuleAction), fromType)) Then
                Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
                parserContext.NextToken
                Dim arguments As List([Of] CodeExpression) = Me.ParseArgumentList(parserContext)
                action = DirectCast(Me.ConstructCustomType(fromType, arguments, startPosition), RuleAction)
                parserContext.exprPositions.Item(action) = currentToken.StartPosition
                Me.ValidateAction(parserContext, action)
                Return action
            End If
            parserContext.RestoreCurrentToken(tokenValue)
            Dim codeDomStatement As CodeStatement = Me.ParseAssignmentStatement(parserContext)
            If (Not codeDomStatement Is Nothing) Then
                action = New RuleStatementAction(codeDomStatement)
            End If
            Return action
        End Function

        Friend Function ParseStatementList(ByVal statementString As String) As List([Of] RuleAction)
            Me.validation.Errors.Clear
            Dim parserContext As New ParserContext(statementString)
            Return Me.ParseStatements(parserContext)
        End Function

        Private Function ParseStatements(ByVal parserContext As ParserContext) As List([Of] RuleAction)
            Dim list As New List([Of] RuleAction)
            Do While (parserContext.CurrentToken.TokenID <> TokenID.EndOfInput)
                Dim item As RuleAction = Me.ParseStatement(parserContext)
                If (item Is Nothing) Then
                    Return list
                End If
                list.Add(item)
                Do While (parserContext.CurrentToken.TokenID = TokenID.Semicolon)
                    parserContext.NextToken
                Loop
            Loop
            Return list
        End Function

        Private Function ParseTypeRef(ByVal parserContext As ParserContext, ByVal type As Type, ByVal typePosition As Integer, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim expression As CodeExpression = Nothing
            If ((parserContext.CurrentToken.TokenID = TokenID.LParen) AndAlso TypeProvider.IsAssignable(GetType(IRuleExpression), type)) Then
                Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
                parserContext.NextToken
                Dim arguments As List([Of] CodeExpression) = Me.ParseArgumentList(parserContext)
                expression = DirectCast(Me.ConstructCustomType(type, arguments, startPosition), CodeExpression)
                parserContext.exprPositions.Item(expression) = startPosition
                Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
                Return expression
            End If
            Dim typeRef As New CodeTypeReference(type)
            Me.validation.AddTypeReference(typeRef, type)
            expression = New CodeTypeReferenceExpression(typeRef)
            parserContext.exprPositions.Item(expression) = typePosition
            Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            Return expression
        End Function

        Private Function ParseUnadornedFieldOrProperty(ByVal parserContext As ParserContext, ByVal name As String, ByVal namePosition As Integer, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim thisType As Type = Me.Validator.ThisType
            Dim info As MemberInfo = Me.Validator.ResolveFieldOrProperty(thisType, name)
            If (info Is Nothing) Then
                Dim message As String = String.Format(CultureInfo.CurrentCulture, Messages.UnknownFieldOrProperty, New Object() { name, RuleDecompiler.DecompileType(thisType) })
                Throw New RuleSyntaxException(390, message, namePosition)
            End If
            Dim isStatic As Boolean = False
            Dim info2 As FieldInfo = [TryCast](info,FieldInfo)
            If (Not info2 Is Nothing) Then
                isStatic = info2.IsStatic
            Else
                Dim info3 As PropertyInfo = [TryCast](info,PropertyInfo)
                If (Not info3 Is Nothing) Then
                    Dim accessors As MethodInfo() = info3.GetAccessors(True)
                    Dim i As Integer
                    For i = 0 To accessors.Length - 1
                        If accessors(i).IsStatic Then
                            isStatic = True
                            Exit For
                        End If
                    Next i
                End If
            End If
            Dim targetObject As CodeExpression = Nothing
            If isStatic Then
                targetObject = New CodeTypeReferenceExpression(thisType)
            Else
                targetObject = New CodeThisReferenceExpression
            End If
            Dim expression As CodeExpression = Nothing
            If (Not info2 Is Nothing) Then
                expression = New CodeFieldReferenceExpression(targetObject, name)
            Else
                expression = New CodePropertyReferenceExpression(targetObject, name)
            End If
            parserContext.exprPositions.Item(expression) = namePosition
            Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            Return expression
        End Function

        Friend Function ParseUnadornedMemberIdentifier(ByVal parserContext As ParserContext, ByVal symbol As MemberSymbol, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
            parserContext.NextToken
            If (parserContext.CurrentToken.TokenID = TokenID.LParen) Then
                Return Me.ParseUnadornedMethodInvoke(parserContext, symbol.Name, True)
            End If
            Return Me.ParseUnadornedFieldOrProperty(parserContext, symbol.Name, startPosition, assignIsEquality)
        End Function

        Private Function ParseUnadornedMethodInvoke(ByVal parserContext As ParserContext, ByVal methodName As String, ByVal assignIsEquality As Boolean) As CodeExpression
            Dim thisType As Type = Me.Validator.ThisType
            Dim startPosition As Integer = parserContext.CurrentToken.StartPosition
            parserContext.NextToken
            If ((parserContext.CurrentToken.TokenID = TokenID.EndOfInput) AndAlso parserContext.provideIntellisense) Then
                parserContext.SetMethodCompletions(thisType, thisType, methodName, True, True, Me.validation)
                Return Nothing
            End If
            Dim argumentExprs As List([Of] CodeExpression) = Me.ParseArgumentList(parserContext)
            Dim methodBindingFlags As BindingFlags = (BindingFlags.FlattenHierarchy Or (BindingFlags.NonPublic Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance))))
            Dim error As ValidationError = Nothing
            Dim info As RuleMethodInvokeExpressionInfo = Me.validation.ResolveMethod(thisType, methodName, methodBindingFlags, argumentExprs, [error])
            If (info Is Nothing) Then
                Throw New RuleSyntaxException([error].ErrorNumber, [error].ErrorText, startPosition)
            End If
            Dim methodInfo As MethodInfo = info.MethodInfo
            Dim targetObject As CodeExpression = Nothing
            If methodInfo.IsStatic Then
                targetObject = New CodeTypeReferenceExpression(thisType)
            Else
                targetObject = New CodeThisReferenceExpression
            End If
            Dim expression As CodeExpression = New CodeMethodInvokeExpression(targetObject, methodName, argumentExprs.ToArray)
            parserContext.exprPositions.Item(expression) = startPosition
            Me.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
            Return expression
        End Function

        Private Function ParseUnaryExpression(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck) As CodeExpression
            Dim currentToken As Token = parserContext.CurrentToken
            Dim expression As CodeExpression = Nothing
            If (currentToken.TokenID = TokenID.Not) Then
                Dim startPosition As Integer = currentToken.StartPosition
                parserContext.NextToken
                expression = New CodeBinaryOperatorExpression(Me.ParseUnaryExpression(parserContext, True, check), CodeBinaryOperatorType.ValueEquality, New CodePrimitiveExpression(False))
                parserContext.exprPositions.Item(expression) = startPosition
                Me.ValidateExpression(parserContext, expression, assignIsEquality, check)
                Return expression
            End If
            If (currentToken.TokenID = TokenID.Minus) Then
                Dim num2 As Integer = currentToken.StartPosition
                parserContext.NextToken
                expression = Me.ParseUnaryExpression(parserContext, True, check)
                expression = New CodeBinaryOperatorExpression(New CodePrimitiveExpression(0), CodeBinaryOperatorType.Subtract, expression)
                parserContext.exprPositions.Item(expression) = num2
                Me.ValidateExpression(parserContext, expression, assignIsEquality, check)
                Return expression
            End If
            If (currentToken.TokenID = TokenID.LParen) Then
                Dim num3 As Integer = currentToken.StartPosition
                Dim tokenValue As Integer = parserContext.SaveCurrentToken
                currentToken = parserContext.NextToken
                Dim type As Type = Me.TryParseTypeSpecifier(parserContext, assignIsEquality)
                If ((type Is Nothing) OrElse (parserContext.CurrentToken.TokenID <> TokenID.RParen)) Then
                    parserContext.RestoreCurrentToken(tokenValue)
                    Return Me.ParsePostfixExpression(parserContext, assignIsEquality, check)
                End If
                If (parserContext.CurrentToken.TokenID <> TokenID.RParen) Then
                    Throw New RuleSyntaxException(&H184, Messages.Parser_MissingRParenInSubexpression, parserContext.CurrentToken.StartPosition)
                End If
                parserContext.NextToken
                expression = Me.ParseUnaryExpression(parserContext, True, check)
                Dim typeRef As New CodeTypeReference(type)
                Me.validation.AddTypeReference(typeRef, type)
                expression = New CodeCastExpression(typeRef, expression)
                parserContext.exprPositions.Item(expression) = num3
                Me.ValidateExpression(parserContext, expression, assignIsEquality, check)
                Return expression
            End If
            Return Me.ParsePostfixExpression(parserContext, assignIsEquality, check)
        End Function

        Private Function TryParsePostfixOperator(ByVal parserContext As ParserContext, ByVal primaryExpr As CodeExpression, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck) As CodeExpression
            Dim expression As CodeExpression = Nothing
            If (parserContext.CurrentToken.TokenID = TokenID.Dot) Then
                Return Me.ParseMemberOperator(parserContext, primaryExpr, assignIsEquality, check)
            End If
            If (parserContext.CurrentToken.TokenID = TokenID.LBracket) Then
                expression = Me.ParseElementOperator(parserContext, primaryExpr, assignIsEquality)
            End If
            Return expression
        End Function

        Private Function TryParseTypeName(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As Type
            Dim expressionType As Type = Nothing
            Dim currentToken As Token = parserContext.CurrentToken
            If (currentToken.TokenID = TokenID.TypeName) Then
                expressionType = DirectCast(currentToken.Value, Type)
                parserContext.NextToken
                Return expressionType
            End If
            If (currentToken.TokenID = TokenID.Identifier) Then
                Dim symbol As Symbol = Nothing
                If Me.globalUniqueSymbols.TryGetValue(CStr(currentToken.Value), symbol) Then
                    Dim expression As CodeExpression = symbol.ParseRootIdentifier(Me, parserContext, assignIsEquality)
                    If TypeOf expression Is CodeTypeReferenceExpression Then
                        expressionType = Me.validation.ExpressionInfo(expression).ExpressionType
                    End If
                End If
            End If
            Return expressionType
        End Function

        Private Function TryParseTypeSpecifier(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As Type
            Dim baseType As Type = Me.TryParseTypeName(parserContext, assignIsEquality)
            If (Not baseType Is Nothing) Then
                baseType = Parser.ParseArrayType(parserContext, baseType)
            End If
            Return baseType
        End Function

        Private Function TryParseTypeSpecifierWithOptionalSize(ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean, <Out> ByRef size As CodeExpression) As Type
            Dim type As Type = Nothing
            size = Nothing
            Dim currentToken As Token = parserContext.CurrentToken
            type = Me.TryParseTypeName(parserContext, assignIsEquality)
            If ((Not type Is Nothing) AndAlso (parserContext.CurrentToken.TokenID = TokenID.LBracket)) Then
                If (parserContext.NextToken.TokenID <> TokenID.RBracket) Then
                    size = Me.ParseBinaryExpression(parserContext, 0, False, ValueCheck.Read)
                Else
                    size = Parser.defaultSize
                End If
                If (parserContext.CurrentToken.TokenID <> TokenID.RBracket) Then
                    Throw New RuleSyntaxException(410, Messages.Parser_MissingCloseSquareBracket1, parserContext.CurrentToken.StartPosition)
                End If
                parserContext.NextToken
            End If
            Return type
        End Function

        Private Sub ValidateAction(ByVal parserContext As ParserContext, ByVal action As RuleAction)
            If Not action.Validate(Me.validation) Then
                Dim error As ValidationError = Me.Validator.Errors.Item(0)
                Dim key As Object = [error].UserData.Item("ErrorObject")
                Dim num As Integer = 0
                parserContext.exprPositions.TryGetValue(key, num)
                Throw New RuleSyntaxException([error].ErrorNumber, [error].ErrorText, num)
            End If
        End Sub

        Private Sub ValidateExpression(ByVal parserContext As ParserContext, ByVal expression As CodeExpression, ByVal assignIsEquality As Boolean, ByVal check As ValueCheck)
            If ((parserContext.CurrentToken.TokenID = TokenID.Assign) AndAlso Not assignIsEquality) Then
                check = ValueCheck.Write
            End If
            Dim info As RuleExpressionInfo = Nothing
            If ((check And ValueCheck.Read) <> ValueCheck.Unknown) Then
                info = RuleExpressionWalker.Validate(Me.Validator, expression, False)
                If ((Not info Is Nothing) AndAlso ((check And ValueCheck.Write) <> ValueCheck.Unknown)) Then
                    info = RuleExpressionWalker.Validate(Me.Validator, expression, True)
                End If
            ElseIf ((check And ValueCheck.Write) <> ValueCheck.Unknown) Then
                info = RuleExpressionWalker.Validate(Me.Validator, expression, True)
            End If
            If ((info Is Nothing) AndAlso (Me.Validator.Errors.Count > 0)) Then
                Dim error As ValidationError = Me.Validator.Errors.Item(0)
                Dim key As Object = [error].UserData.Item("ErrorObject")
                Dim num As Integer = 0
                parserContext.exprPositions.TryGetValue(key, num)
                Throw New RuleSyntaxException([error].ErrorNumber, [error].ErrorText, num)
            End If
        End Sub

        Private Sub ValidateStatement(ByVal parserContext As ParserContext, ByVal statement As CodeStatement)
            If (Not CodeDomStatementWalker.Validate(Me.Validator, statement) AndAlso (Me.Validator.Errors.Count > 0)) Then
                Dim error As ValidationError = Me.Validator.Errors.Item(0)
                Dim key As Object = [error].UserData.Item("ErrorObject")
                Dim num As Integer = 0
                parserContext.exprPositions.TryGetValue(key, num)
                Throw New RuleSyntaxException([error].ErrorNumber, [error].ErrorText, num)
            End If
        End Sub


        ' Properties
        Private ReadOnly Property Validator As RuleValidation
            Get
                Return Me.validation
            End Get
        End Property


        ' Fields
        Private Shared defaultSize As CodeExpression = New CodePrimitiveExpression(0)
        Private globalUniqueSymbols As Dictionary([Of] String, Symbol) = New Dictionary([Of] String, Symbol)
        Private localUniqueSymbols As Dictionary([Of] String, Symbol) = New Dictionary([Of] String, Symbol)
        Private Shared ReadOnly precedences As BinaryPrecedenceDescriptor() = New BinaryPrecedenceDescriptor() { New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.Or, CodeBinaryOperatorType.BooleanOr) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.And, CodeBinaryOperatorType.BooleanAnd) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.BitOr, CodeBinaryOperatorType.BitwiseOr) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.BitAnd, CodeBinaryOperatorType.BitwiseAnd) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.Equal, CodeBinaryOperatorType.ValueEquality), New BinaryOperationDescriptor(TokenID.Assign, CodeBinaryOperatorType.ValueEquality), New NotEqualOperationDescriptor(TokenID.NotEqual) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.Less, CodeBinaryOperatorType.LessThan), New BinaryOperationDescriptor(TokenID.LessEqual, CodeBinaryOperatorType.LessThanOrEqual), New BinaryOperationDescriptor(TokenID.Greater, CodeBinaryOperatorType.GreaterThan), New BinaryOperationDescriptor(TokenID.GreaterEqual, CodeBinaryOperatorType.GreaterThanOrEqual) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.Plus, CodeBinaryOperatorType.Add), New BinaryOperationDescriptor(TokenID.Minus, CodeBinaryOperatorType.Subtract) }), New BinaryPrecedenceDescriptor(New BinaryOperationDescriptor() { New BinaryOperationDescriptor(TokenID.Multiply, CodeBinaryOperatorType.Multiply), New BinaryOperationDescriptor(TokenID.Divide, CodeBinaryOperatorType.Divide), New BinaryOperationDescriptor(TokenID.Modulus, CodeBinaryOperatorType.Modulus) }) }
        Private validation As RuleValidation

        ' Nested Types
        Private Class BinaryOperationDescriptor
            ' Methods
            Friend Sub New(ByVal token As TokenID, ByVal codeDomOperator As CodeBinaryOperatorType)
                Me.token = token
                Me.codeDomOperator = codeDomOperator
            End Sub

            Friend Overridable Function CreateBinaryExpression(ByVal left As CodeExpression, ByVal right As CodeExpression, ByVal operatorPosition As Integer, ByVal parser As Parser, ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeBinaryOperatorExpression
                Dim expression As New CodeBinaryOperatorExpression(left, Me.codeDomOperator, right)
                parserContext.exprPositions.Item(expression) = operatorPosition
                parser.ValidateExpression(parserContext, expression, assignIsEquality, ValueCheck.Read)
                Return expression
            End Function


            ' Properties
            Friend ReadOnly Property Token As TokenID
                Get
                    Return Me.token
                End Get
            End Property


            ' Fields
            Private codeDomOperator As CodeBinaryOperatorType
            Private token As TokenID
        End Class

        Private Class BinaryPrecedenceDescriptor
            ' Methods
            Friend Sub New(ByVal ParamArray operations As BinaryOperationDescriptor())
                Me.operations = operations
            End Sub

            Friend Function FindOperation(ByVal token As TokenID) As BinaryOperationDescriptor
                Dim descriptor As BinaryOperationDescriptor
                For Each descriptor In Me.operations
                    If (descriptor.Token = token) Then
                        Return descriptor
                    End If
                Next
                Return Nothing
            End Function


            ' Fields
            Private operations As BinaryOperationDescriptor()
        End Class

        Private Class CandidateConstructor
            ' Methods
            Friend Sub New(ByVal ctor As ConstructorInfo, ByVal ctorArgs As Object(), ByVal isExpandedMatch As Boolean)
                Me.ctor = ctor
                Me.ctorArgs = ctorArgs
                Me.isExpandedMatch = isExpandedMatch
            End Sub

            Friend Function CompareConstructor(ByVal other As CandidateConstructor) As Integer
                Dim num As Integer = 1
                Dim num2 As Integer = -1
                If (Not Me.isExpandedMatch AndAlso other.isExpandedMatch) Then
                    Return num
                End If
                If (Me.isExpandedMatch AndAlso Not other.isExpandedMatch) Then
                    Return num2
                End If
                If (Me.isExpandedMatch AndAlso other.isExpandedMatch) Then
                    Dim length As Integer = Me.ctor.GetParameters.Length
                    Dim num5 As Integer = other.ctor.GetParameters.Length
                    If (length > num5) Then
                        Return num
                    End If
                    If (num5 > length) Then
                        Return num2
                    End If
                End If
                Return 0
            End Function

            Friend Function InvokeConstructor() As Object
                Return Me.ctor.Invoke(Me.ctorArgs)
            End Function


            ' Fields
            Private ctor As ConstructorInfo
            Private ctorArgs As Object()
            Private isExpandedMatch As Boolean
        End Class

        Private Class NotEqualOperationDescriptor
            Inherits BinaryOperationDescriptor
            ' Methods
            Friend Sub New(ByVal token As TokenID)
                MyBase.New(token, CodeBinaryOperatorType.IdentityInequality)
            End Sub

            Friend Overrides Function CreateBinaryExpression(ByVal left As CodeExpression, ByVal right As CodeExpression, ByVal operatorPosition As Integer, ByVal parser As Parser, ByVal parserContext As ParserContext, ByVal assignIsEquality As Boolean) As CodeBinaryOperatorExpression
                Dim expression As New CodePrimitiveExpression(False)
                parserContext.exprPositions.Item(expression) = operatorPosition
                Dim expression2 As New CodeBinaryOperatorExpression(left, CodeBinaryOperatorType.ValueEquality, right)
                parserContext.exprPositions.Item(expression2) = operatorPosition
                expression2 = New CodeBinaryOperatorExpression(expression2, CodeBinaryOperatorType.ValueEquality, expression)
                parserContext.exprPositions.Item(expression2) = operatorPosition
                parser.ValidateExpression(parserContext, expression2, assignIsEquality, ValueCheck.Read)
                Return expression2
            End Function

        End Class

        <Flags> _
        Private Enum ValueCheck
            ' Fields
            Read = 1
            Unknown = 0
            Write = 2
        End Enum
    End Class
End Namespace

